#pragma once

#include <iostream>
#include <string>
#include <unistd.h>

#include <jsoncpp/json/json.h>

#include "../comm/until.hpp"
#include "../comm/log.hpp"
#include "compiler.hpp"
#include "runner.hpp"

/*************************
*
*此模块用来接受json串，形成唯一路径的文件
*并编译运行，返回运行后的json串
*
************************/

namespace NS_COMPILE_RUN
{
    using namespace NS_UNTIL;
    using namespace NS_LOG;
    using namespace NS_COMPILER;
    using namespace NS_RUNNER;


    static void RemoveTepFile(const std::string& file_name)
    {
        std::string src=PathUntil::Src(file_name);
        if(FileUntil::IsExistExe(src))  unlink(src.c_str());

        std::string _exe=PathUntil::Exe(file_name);
        if(FileUntil::IsExistExe(_exe))  unlink(_exe.c_str());
        
        std::string compile_err=PathUntil::Compile_Error(file_name);
        if(FileUntil::IsExistExe(compile_err)) unlink(compile_err.c_str());

        std::string _stdin=PathUntil::Stdin(file_name);
        if(FileUntil::IsExistExe(_stdin)) unlink(_stdin.c_str());

        std::string _stdout=PathUntil::Stdout(file_name);
        if(FileUntil::IsExistExe(_stdout)) unlink(_stdout.c_str());

        std::string _stderr=PathUntil::stderror(file_name);
        if(FileUntil::IsExistExe(_stderr)) unlink(_stderr.c_str());
    }
    class compile_and_run
    {
    public:
        compile_and_run() {}
        ~compile_and_run() {}

    public:
        static std::string CodeToDesc(int status_code,const std::string&file_name)
        {
            switch(status_code)
            {
                case 0:
                    return "编译运行成功!";
                case -1:
                    return "提交代码为空";
                case -2:
                    return "未知错误";
                case -3:
                {
                    std::string content;
                    FileUntil::ReadFile(PathUntil::Compile_Error(file_name),&content,true);
                    return content;
                }
                case SIGABRT: //6
                    return "段错误:可能是空间超时";
                case SIGXCPU:
                    return "段错误:可能是时间超时";
                case SIGFPE : //8
                    return "div zore error";
                default:
                    return "未知错误";
            }
        }


        /**************
         *in_json
         *   code:#include...
         *   input:用户代码的提交，不处理
         *   cup_limit:
         *   mem_limit:
         *out_json
         *必填:
         *   status_code,Desc
         *选填:
         *   stdout
         *   stderr
         *
         ***************/
        static void Start(const std::string &in_json, std::string *out_json)
        {
            Json::Value in_value;
            Json::Reader reader;
            reader.parse(in_json, in_value);

            // 获取代码
            std::string code = in_value["code"].asString();
            std::string input = in_value["input"].asString();
            int cpu_limit = in_value["cpu_limit"].asInt();
            int mem_limit = in_value["mem_limit"].asInt();

            int status_code = 0;
            int result_code;
            Json::Value out_value;
            // 形成唯一的文件名,并形成源文件
            std::string file_name = FileUntil::UniqFileName();

            if(!FileUntil::WriteFile(PathUntil::Src(file_name),code))
            {
                status_code=-2;
                goto END;
            }

            if (!code.size())
            {
                status_code = -1; // 文件为空
                goto  END;
            }

            //编译
            if(!compiler::Compile(file_name))
            {
                status_code=-3;//编译失败
                goto END;
            }

            result_code=runner::Run(file_name,cpu_limit,mem_limit);
            if(result_code<0)
            {
                status_code=-2; //内部错误
            }
            else if(result_code>0)
            {
                status_code=result_code; //信号异常
            }
            else
            {
                status_code=0;
            }

        END:
            out_value["status_code"]=status_code;
            out_value["reason"]=CodeToDesc(status_code,file_name);
            //编译运行结束，提取标准输出和标准错误
            if(status_code==0)
            {
                std::string _stdout;
                FileUntil::ReadFile(PathUntil::Stdout(file_name),&_stdout,true);
                out_value["_stdout"]=_stdout;

                std::string _stderr;
                FileUntil::ReadFile(PathUntil::stderror(file_name),&_stderr,true);
                out_value["stderr"]=_stderr;
            }
            //形成输出Json串
            Json::StyledWriter writer;
            *out_json=writer.write(out_value);
        
            //RemoveTepFile(file_name);

        }
    
    };

    
}